package com.lastb7.swagger.controller;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.jfinal.core.Action;
import com.jfinal.core.ActionKey;
import com.jfinal.core.Controller;
import com.jfinal.core.JFinal;
import com.jfinal.kit.Base64Kit;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.template.Engine;
import com.lastb7.swagger.annotation.ApiNoAuthorize;
import com.lastb7.swagger.annotation.ApiRes;
import com.lastb7.swagger.annotation.ApiResCustom;
import com.lastb7.swagger.annotation.ApiResProperty;
import com.lastb7.swagger.common.SwaggerConst;
import com.lastb7.swagger.enumeration.ApiEnum;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import sun.reflect.generics.reflectiveObjects.WildcardTypeImpl;

/**
 * Swagger UI Controller
 *
 * @author: lbq
 * 联系方式: 526509994@qq.com
 * 创建日期: 2020/9/16
 */
public class SwaggerController extends Controller {

    /**
     * swagger tag
     */
    private List<Kv> tagsList = new ArrayList<>();

    /**
     * swagger models
     */
    private Map<String, Kv> definitionsMap = new LinkedHashMap<>();

    /**
     * swagger path
     */
    private List pathList = new ArrayList();

    /**
     * 通用返回类 名称
     */
    private String commonResName;

    /**
     * 通用返回类 返回值
     */
    private List commonResProperties;

    /**
     * 分组包配置的basePath
     */
    private String groupPackageBasePath;

    /**
     * 用于支持FastControllerFactory使用场景
     * 参照FastControllerFactory注释进行修改
     */
    @Override
    protected void _clear_() {
        // 调用父类的清除方法清掉父类中的属性值
        super._clear_();
        // 清除本类中声明的属性的值
        this.tagsList = new ArrayList<>();
        this.definitionsMap = new LinkedHashMap<>();
        this.pathList = new ArrayList();
    }

    /**
     * 默认转发
     */
    public void index() {
        Engine engine = Engine.use();

        engine.setDevMode(true);
        engine.setToClassPathSourceFactory();

        renderHtml(engine.getTemplate("/META-INF/resources/doc.html").renderToString());
    }

    /**
     * 获取分组信息
     */
    @ActionKey("swagger-resources")
    public void resources() {
        Kv kv = new Kv();
        kv.set("swagger_resources", SwaggerConst.CONFIG.get("swagger_resources"));
        kv.set("swaggerVersion", SwaggerConst.CONFIG.get("swaggerVersion"));

        renderJson(Engine.use("swagger").getTemplate("/swagger-resources.jf").renderToString(kv));
    }

    /**
     * 获取api接口解析JSON
     */
    public void api() throws IOException {
        if (!this.basicAuth()) {
            this.response401();

            this.renderNull();
            return;
        }

        // 从内存缓存中读取
        Integer cacheSecond = SwaggerConst.CONFIG.getInt("cacheSecond", 0);
        if (cacheSecond > 0) {
            String apiJson = SwaggerConst.API_CACHE.getStr("apiJson");
            Long currTime = SwaggerConst.API_CACHE.getLong("currTime");

            // 判断是否超时
            if (null != apiJson && null != currTime && (currTime + cacheSecond * 1000 > System.currentTimeMillis())) {
                this.renderJson(apiJson);
                return;
            }
        }

        // 解析通用返回
        Kv commonResKv = this.parseSwaggerModel(SwaggerConst.COMMON_RES);
        this.commonResName = commonResKv.getStr("name");
        this.commonResProperties = (List) commonResKv.get("properties");

        // 解析JSON
        this.parseGroupPackage(this.getPara("group", ""));

        Kv kv = new Kv();
        kv.set("swagger", SwaggerConst.CONFIG.getProperties());
        kv.set("host", this.getHost());

        kv.set("tags", this.tagsList);
        kv.set("paths", this.pathList);
        kv.set("definitions", this.definitionsMap);

        kv.set("groupPackageBasePath", this.groupPackageBasePath);

        String apiJson = Engine.use("swagger").getTemplate("/api-docs.jf").renderToString(kv);

        System.out.println("解析....");

        // 放入内存缓存中
        if (cacheSecond > 0) {
            SwaggerConst.API_CACHE.put("apiJson", apiJson);
            SwaggerConst.API_CACHE.put("currTime", System.currentTimeMillis());
        }

        renderJson(apiJson);
    }

    /**
     * 解析分组包
     *
     * @param groupPackage 分组包名
     */
    private void parseGroupPackage(String groupPackage) {
        // 解析分组包basePath
        this.parseGroupPackageBasePath(groupPackage);

        Map<Class<? extends Controller>, List<Action>> classMap = this.getApiAction(groupPackage);
        classMap.keySet().forEach((Class<? extends Controller> clazz) -> {
            List<Action> actions = classMap.get(clazz);

            // 解析controller
            this.parseController(clazz, actions);

        });
    }

    /**
     * 解析分组包basePath
     */
    private void parseGroupPackageBasePath(String groupPackage) {
        String swaggerResources = SwaggerConst.CONFIG.get("swagger_resources");
        String[] arrs = swaggerResources.split(",");
        for (String resources : arrs) {
            String[] items = resources.split("#");
            if (items.length > 2 && items[1].equals(groupPackage)) {
                String basePath = items[2];
                this.groupPackageBasePath = basePath;
                break;
            }
        }
    }

    /**
     * 从JFinal中获取全部Action
     */
    private Map<Class<? extends Controller>, List<Action>> getApiAction(String basePackage) {
        Map<Class<? extends Controller>, List<Action>> apiMap = new HashMap<>(16);

        JFinal.me().getAllActionKeys().forEach(actionKey -> {
            Action action = JFinal.me().getAction(actionKey, new String[1]);
            Class<? extends Controller> controller = action.getControllerClass();

            if (!controller.getName().startsWith(basePackage)) {
                return;
            }

            if (apiMap.containsKey(controller)) {
                if (action.getMethod().isAnnotationPresent(ApiOperation.class)) {
                    List<Action> actions = apiMap.get(controller);
                    if (!actions.contains(action)) {
                        actions.add(action);
                        apiMap.put(controller, actions);
                    }
                }
            } else {
                if (controller.isAnnotationPresent(Api.class)) {
                    if (action.getMethod().isAnnotationPresent(ApiOperation.class)) {
                        List<Action> actions = new ArrayList<>();
                        actions.add(action);
                        apiMap.put(controller, actions);
                    }
                }
            }
        });

        // Controller排序
        List<Class<? extends Controller>> ctlList = new ArrayList<>(apiMap.keySet());
        ctlList.sort(Comparator.comparingInt(clazz -> {
            int position = clazz.getAnnotation(Api.class).position();
            return position == 0 ? Integer.MAX_VALUE : position;
        }));

        // 方法排序
        Map<Class<? extends Controller>, List<Action>> result = new LinkedHashMap<>();
        ctlList.forEach(i -> {
            List<Action> actions = apiMap.get(i);
            actions.sort(Comparator.comparingInt(action -> {
                int position = action.getMethod().getAnnotation(ApiOperation.class).position();
                return position == 0 ? Integer.MAX_VALUE : position;
            }));
            result.put(i, actions);
        });

        return result;
    }

    /**
     * 解析controller
     */
    private void parseController(Class<? extends Controller> clazz, List<Action> actions) {
        // controller 信息
        Api api = clazz.getAnnotation(Api.class);
        boolean hidden = api.hidden();
        if (hidden) {
            return;
        }

        for (String tags : api.tags()) {
            Kv tag = new Kv();
            tag.set("name", tags);
            tag.set("controllerKey", actions.get(0).getControllerPath());
            tag.set("controllerName", clazz.getSimpleName());

            this.tagsList.add(tag);
        }

        // 解析action
        this.parseAction(actions);
    }

    /**
     * 解析action
     */
    private void parseAction(List<Action> actions) {
        actions.forEach((Action action) -> {
            Method method = action.getMethod();

            ApiOperation apiAction = method.getAnnotation(ApiOperation.class);

            if (apiAction.hidden()) {
                return;
            }

            String controllerKey = this.getControllerKey(action.getControllerPath());
            String actionName = action.getMethodName();

            Kv actionKv = new Kv();
            actionKv.set("tags", StrKit.notBlank(apiAction.tags()) ? apiAction.tags() : actions.get(0).getControllerClass().getAnnotation(Api.class).tags())
                    .set("summary", apiAction.value())
                    .set("description", apiAction.notes())
                    .set("deprecated", method.isAnnotationPresent(Deprecated.class))
                    .set("noAuthorize", method.isAnnotationPresent(ApiNoAuthorize.class) || actions.get(0).getControllerClass().isAnnotationPresent(ApiNoAuthorize.class))
                    .set("parameters", this.parseActionParameters(method))
                    .set("responses", this.parseActionResponse(controllerKey, actionName, method))
                    .set("methods", StrKit.isBlank(apiAction.httpMethod()) ? ApiEnum.METHOD_GET : apiAction.httpMethod())
                    .set("consumes", StrKit.isBlank(apiAction.consumes()) ? ApiEnum.CONSUMES_URLENCODED : apiAction.consumes())
                    .set("produces", StrKit.isBlank(apiAction.produces()) ? ApiEnum.PRODUCES_DEFAULT : apiAction.produces())
                    .set("controllerKey", controllerKey)
                    .set("actionName", actionName);

            pathList.add(actionKv);
        });

    }

    /**
     * 解析action 参数文档
     */
    private List<Kv> parseActionParameters(Method method) {
        // 获取参数注解信息
        List<ApiImplicitParam> params = new ArrayList<>();
        if (method.isAnnotationPresent(ApiImplicitParams.class)) {
            params.addAll(Arrays.asList(method.getAnnotation(ApiImplicitParams.class).value()));
        }
        if (method.isAnnotationPresent(ApiImplicitParams.class)) {
            ApiImplicitParam[] paramArray = method.getAnnotationsByType(ApiImplicitParam.class);
            params.addAll(Arrays.asList(paramArray));
        }

        // 构建参数列表(包含全局参数)
        List<Kv> paramList = new ArrayList<>();

        params.forEach(param -> {
            Kv kv = Kv.by("name", param.name())
                    .set("description", param.value())
                    .set("required", param.required())
                    .set("format", param.format())
                    .set("defaultValue", param.defaultValue())
                    .set("allowMultiple", param.allowMultiple())
                    .set("schema", this.toParameterSchema(param))
                    .set("dataType", StrKit.isBlank(param.dataType()) ? ApiEnum.STRING : param.dataType())
                    .set("paramType", StrKit.isBlank(param.paramType()) ? ApiEnum.PARAM_TYPE_QUERY : param.paramType());

            paramList.add(kv);
        });
        return paramList;
    }

    /**
     * 解析action 返回文档
     */
    private List parseActionResponse(String controllerKey, String actionName, Method method) {
        List responseList = new ArrayList();

        SwaggerConst.HTTP_CODE.forEach((key, value) -> {
            if (key == 200) {
                responseList.add(Kv.by("name", key).set("description", value)
                        .set("schema", this.parseResponse(controllerKey, actionName, method)));
            } else {
                responseList.add(Kv.by("name", key).set("description", value));
            }

        });
        return responseList;
    }

    /**
     * 解析返回值
     */
    private String parseResponse(String controllerKey, String actionName, Method method) {
        // swagger model 引用
        String swaggerModelName;

        List<ApiResProperty> responses = new ArrayList<>();
        if (method.isAnnotationPresent(ApiRes.class)) {
            responses.addAll(Arrays.asList(method.getAnnotation(ApiRes.class).value()));
        }
        if (method.isAnnotationPresent(ApiRes.class)) {
            ApiResProperty[] paramArray = method.getAnnotationsByType(ApiResProperty.class);
            responses.addAll(Arrays.asList(paramArray));
        }

        // 2.9.1 实验性质 自定义返回值
        ApiResCustom apiResCustom = method.getAnnotation(ApiResCustom.class);
        if (null != apiResCustom && apiResCustom.value() != Void.class) {
            Kv commonResKv = this.parseSwaggerModel(apiResCustom.value());
            swaggerModelName = commonResKv.getStr("name");
            return swaggerModelName;
        }

        if (responses.size() == 0) {
            swaggerModelName = this.commonResName;
        } else {
            // 将参数放入commonRes中,作为新的swagger Model引用(knife4j 约定)
            Kv swaggerModelKv = this.parseSwaggerModel(controllerKey, actionName, responses);
            swaggerModelName = swaggerModelKv.getStr("name");

            // 在data中返回参数
            if (SwaggerConst.RESPONSE_IN_DATA) {
                swaggerModelName = this.toResponseInData(swaggerModelName);
            }
        }

        return swaggerModelName;
    }

    /**
     * 在data中返回
     */
    private String toResponseInData(String swaggerModelName) {
        Kv fieldKv = new Kv();
        List propertiesList = new ArrayList();
        propertiesList.addAll(this.commonResProperties);


        fieldKv.set("key", "data");
        fieldKv.set("name", swaggerModelName);
        fieldKv.set("description", "返回值");
        fieldKv.set("type", ApiEnum.RES_OBJECT);

        propertiesList.add(fieldKv);

        swaggerModelName = this.commonResName + "«" + swaggerModelName + "»";

        Kv kv = new Kv();
        kv.set("properties", propertiesList);
        kv.set("name", swaggerModelName);

        this.definitionsMap.put(swaggerModelName, kv);
        return swaggerModelName;
    }


    /**
     * swagger models
     */
    private List toDefinitionList(Map<String, Kv> map) {
        List list = new ArrayList();
        map.forEach((key, value) -> list.add(value));
        return list;
    }


    /**
     * 将class解析为swagger model
     */
    private Kv parseSwaggerModel(Class<?> clazz) {
        String modelName = clazz.getSimpleName();

        // 已存在,不重复解析
        Kv modelKv = this.definitionsMap.get(modelName);
        if (null != modelKv) {
            return modelKv;
        }

        // 不是使用ApiModel描述的类,不参与解析
        boolean isApiModel = clazz.isAnnotationPresent(ApiModel.class);
        if (!isApiModel) {
            Kv kv = new Kv();
            kv.set("properties", new ArrayList());
            kv.set("name", modelName);
            kv.set("title", modelName);

            return kv;
        }

        ApiModel apiModel = clazz.getAnnotation(ApiModel.class);
        String title = apiModel.description();

        //解析字段
        Kv fieldKv = new Kv();
        this.parseWithSuperclass(clazz, fieldKv);

        List fieldList = new ArrayList();
        fieldKv.forEach((key, value) -> fieldList.add(value));

        // 字段排序
        fieldList.sort(Comparator.comparingInt(kv -> {
            Integer position = ((Kv) kv).getInt("position");
            return position == 0 ? Integer.MAX_VALUE : position;
        }));


        Kv kv = new Kv();
        kv.set("properties", fieldList);
        kv.set("name", modelName);
        kv.set("title", title);

        this.definitionsMap.put(modelName, kv);

        return kv;
    }


    /**
     * 递归解析父类属性
     */
    public void parseWithSuperclass(Class<?> clazz, Kv fieldList) {
        System.out.println(clazz);
        // 1.判断当前类是否ApiModel注解
        boolean isApiModel = clazz.isAnnotationPresent(ApiModel.class);
        if (!isApiModel) {
            return;
        }

        // 2.判断父类是否是 ApiModel注解
        Class<?> superclass = clazz.getSuperclass();
        isApiModel = superclass.isAnnotationPresent(ApiModel.class);
        if (isApiModel) {
            // 递归解析父类属性
            this.parseWithSuperclass(superclass, fieldList);
        }

        // 3.解析完父类ApiModel注解后,加载当前类注解,用于子类覆盖父类
        this.parseClassField(clazz, fieldList);
    }

    /**
     * 解析 ApiModel
     */
    public void parseClassField(Class<?> clazz, Map fieldMap) {
        boolean isApiModel = clazz.isAnnotationPresent(ApiModel.class);
        if (!isApiModel) {
            return;
        }

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            this.parseApiModelProperty(fieldMap, field);
        }
    }

    /**
     * 解析 ApiModelProperty
     *
     * @param fieldMap
     * @param field
     */
    private void parseApiModelProperty(Map fieldMap, Field field) {
        ApiModelProperty apiField = field.getAnnotation(ApiModelProperty.class);
        if (null == apiField) {
            return;
        }

        if (field.getType() == List.class) {
            // List<Class> 类型
            this.parseApiModelPropertyWithList(field, apiField, fieldMap);
        } else {
            this.parseApiModelPropertyWithoutList(field, apiField, fieldMap);
        }
    }

    /**
     * 解析List类型
     *
     * @param field
     * @param apiField
     * @param fieldMap
     */
    private void parseApiModelPropertyWithList(Field field, ApiModelProperty apiField, Map fieldMap) {
        // List<Class> 类型
        if (field.getType() != List.class) {
            return;
        }
        // 如果是List类型，得到其Generic的类型
        Type genericType = field.getGenericType();
        if (genericType == null) {
            return;
        }
        Kv fieldKv = new Kv();

        // 如果是泛型参数的类型
        if (genericType instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) genericType;
            Type type = pt.getActualTypeArguments()[0];
            if (type instanceof WildcardTypeImpl) {
                // 泛型<?>
                fieldKv.set("name", field.getName());
            } else {
                Class<?> genericClazz = (Class<?>) pt.getActualTypeArguments()[0];
                if (genericClazz.isAnnotationPresent(ApiModel.class)) {
                    Kv swaggerModel = this.parseSwaggerModel(genericClazz);

                    fieldKv.set("name", swaggerModel.getStr("name"));
                    fieldKv.set("isApiModel", true);
                } else {
                    fieldKv.set("name", field.getName());

                    // 解析泛型中的基本类型 api-docs.jf解析时特殊处理
                    Kv itemsKv = new Kv();
                    String fieldType = genericClazz.getSimpleName();
                    this.parseFieldType(fieldType, itemsKv);

                    fieldKv.set("items", itemsKv);
                }
            }
        }

        fieldKv.set("key", field.getName());
        fieldKv.set("description", apiField.value());
        fieldKv.set("type", ApiEnum.RES_OBJECT);
        fieldKv.set("required", apiField.required());
        fieldKv.set("allowMultiple", true);
        fieldKv.set("position", apiField.position());

        fieldMap.put(fieldKv.getStr("name"), fieldKv);

    }

    /**
     * 解析非List类型
     *
     * @param field
     * @param apiField
     * @param fieldMap
     */
    private void parseApiModelPropertyWithoutList(Field field, ApiModelProperty apiField, Map fieldMap) {
        Class<?> typeClazz = field.getType();
        if (typeClazz.isAnnotationPresent(ApiModel.class)) {

            Kv swaggerModel = this.parseSwaggerModel(typeClazz);

            Kv fieldKv = new Kv();

            fieldKv.set("key", field.getName());
            fieldKv.set("name", swaggerModel.getStr("name"));
            fieldKv.set("description", apiField.value());
            fieldKv.set("required", apiField.required());
            fieldKv.set("type", ApiEnum.RES_OBJECT);
            fieldKv.set("position", apiField.position());

            fieldMap.put(fieldKv.getStr("name"), fieldKv);
        } else {
            Kv fieldKv = new Kv();
            fieldKv.set("name", field.getName());
            fieldKv.set("description", apiField.value());
            fieldKv.set("required", apiField.required());
            fieldKv.set("example", apiField.example());
            fieldKv.set("position", apiField.position());

            // 解析基本类型 优先取注解配置的类型, 次选变量定义的类型
            String fieldType = apiField.dataType();
            if (StrKit.isBlank(fieldType)) {
                fieldType = field.getType().getSimpleName();
            }
            this.parseFieldType(fieldType, fieldKv);

            fieldMap.put(fieldKv.getStr("name"), fieldKv);
        }
    }

    /**
     * 解析字段类型
     *
     * @param fieldType 字段类型
     * @param fieldKv   字段属性集合
     */
    private void parseFieldType(String fieldType, Kv fieldKv) {
        switch (fieldType) {
            case "char":
            case "Character":
            case "String":
                fieldKv.set("type", "string");
                break;
            case "boolean":
            case "Boolean":
                fieldKv.set("type", "boolean");
                break;
            case "byte":
            case "Byte":
            case "short":
            case "Short":
            case "int":
            case "Integer":
                fieldKv.set("type", "integer");
                fieldKv.set("format", "int32");
                break;
            case "long":
            case "Long":
                fieldKv.set("type", "integer");
                fieldKv.set("format", "int64");
                break;
            case "double":
            case "Double":
                fieldKv.set("type", "number");
                fieldKv.set("format", "double");
                break;
            case "float":
            case "Float":
                fieldKv.set("type", "number");
                fieldKv.set("format", "float");
                break;
            case "BigDecimal":
                fieldKv.set("type", "number");
                break;
            case "Object":
                // 解析Object类型 api-docs.jf解析时特殊处理
                fieldKv.set("type", "Object");
                break;
            default:
                fieldKv.set("type", "string");
        }
    }

    /**
     * 将action response解析为swagger model
     */
    private Kv parseSwaggerModel(String controllerKey, String actionName, List<ApiResProperty> responses) {
        String modelName = controllerKey + "_" + actionName;

        List propertiesList = new ArrayList();

        // 不在Data中返回参数
        if (!SwaggerConst.RESPONSE_IN_DATA) {
            propertiesList.addAll(this.commonResProperties);
        }

        responses.forEach(apiResponse -> {

            if (apiResponse.dataTypeClass() != Void.class) {
                Kv swaggerModel = this.parseSwaggerModel(apiResponse.dataTypeClass());

                Kv fieldKv = new Kv();

                fieldKv.set("key", apiResponse.name());
                fieldKv.set("name", swaggerModel.getStr("name"));
                fieldKv.set("description", apiResponse.value());
                fieldKv.set("type", ApiEnum.RES_OBJECT);
                fieldKv.set("allowMultiple", apiResponse.allowMultiple());

                propertiesList.add(fieldKv);
            } else {
                Kv fieldKv = new Kv();

                fieldKv.set("name", apiResponse.name());
                fieldKv.set("description", apiResponse.value());
                fieldKv.set("type", StrKit.isBlank(apiResponse.dataType()) ? ApiEnum.RES_STRING : apiResponse.dataType());
                fieldKv.set("format", StrKit.isBlank(apiResponse.format()) ? ApiEnum.FORMAT_STRING : apiResponse.format());
                fieldKv.set("example", apiResponse.example());
                fieldKv.set("exampleEnum", apiResponse.exampleEnum());
                fieldKv.set("allowMultiple", apiResponse.allowMultiple());

                propertiesList.add(fieldKv);
            }
        });

        Kv kv = new Kv();
        kv.set("properties", propertiesList);
        kv.set("name", modelName);

        this.definitionsMap.put(modelName, kv);

        return kv;
    }

    /**
     * 解析对象参数
     */
    private String toParameterSchema(ApiImplicitParam apiParam) {
        if (apiParam.dataTypeClass() != Void.class) {
            Kv swaggerModel = this.parseSwaggerModel(apiParam.dataTypeClass());

            return swaggerModel.getStr("name");
        }
        return null;
    }

    /**
     * 获取host配置
     */
    private String getHost() {
        String host = SwaggerConst.CONFIG.get("host");
        if (StrKit.isBlank(host)) {
            host = getRequest().getServerName();
            if (this.getRequest().getServerPort() != 80) {
                host += ":" + getRequest().getServerPort();
            }
        }
        return host;
    }

    /**
     * 避免JFinal ControllerKey 设置前缀后,与swagger basePath 设置导致前端生成2次
     */
    private String getControllerKey(String actionKey) {
        String basePath = this.groupPackageBasePath;
        if (null == basePath) {
            basePath = SwaggerConst.CONFIG.get("basePath", "");
        }

        String first = actionKey.replaceFirst(basePath, "");

        // actionKey与basePath配置相同,默认为空,由模板控制,不生成/
        String controllerKey = first.length() == 0 ? "" : first.substring(1);
        return controllerKey;
    }

    /**
     * WWW-Authenticate 简单认证
     */
    private boolean basicAuth() throws IOException {
        String basicAuth = SwaggerConst.CONFIG.get("basicAuth");
        if (StrKit.isBlank(basicAuth)) {
            // 未启用简单认证
            return true;
        }

        String authorization = this.getHeader("Authorization");
        if (StrKit.isBlank(authorization)) {
            // 请求头无认证信息
            return false;
        }

        Map<String, String> baseAuthMap = new HashMap<>(16);

        String[] baseAuthArr = basicAuth.split(",");
        for (String auth : baseAuthArr) {
            baseAuthMap.put(auth.split("#")[0], auth.split("#")[1]);
        }

        String nameAndPwd = Base64Kit.decodeToStr(authorization.substring(6));
        String[] upArr = nameAndPwd.split(":");

        if (upArr.length != 2) {
            return false;
        }
        String iptName = upArr[0];
        String iptPwd = upArr[1];

        return iptPwd.equals(baseAuthMap.get(iptName));
    }

    private void response401() throws IOException {
        this.getResponse().setStatus(401);
        this.getResponse().setHeader("WWW-Authenticate", "Basic realm=\"请输入Swagger文档访问账号密码\"");
        this.getResponse().getWriter().write("无权限访问");
    }
}
